package com.users.controller;

import com.alibaba.fastjson.JSON;

import com.alibaba.nacos.common.utils.Md5Utils;
import com.commons.annotations.RequiredToken;
import com.commons.entity.MovieUserInfo;
import com.commons.enums.ResponseCodeEnum;
import com.commons.utils.*;
import com.commons.vo.UpdatePwdVo;
import com.rabbitmq.tools.json.JSONUtil;
import com.sun.org.apache.bcel.internal.generic.NEW;
import com.users.service.MovieUsersServices;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.DigestUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import static com.commons.utils.Constance.CURR_USER;
import static com.commons.utils.Constance.TOKEN_KEY;

/**
 * @author mis_wu
 * @date 2022/3/13 11:48
 */
@RestController
@RequestMapping("/Movie-Users-Services")
@Api(tags = "Movie-Users-Service-Api 电影用户微服务接口")
@Slf4j
@ControllerAdvice
@SuppressWarnings("all")
@RefreshScope
public class MovieUsersController {

    @Resource
    private MovieUsersServices movieUsersServices;

    @Resource
    //按名称注入
    @Qualifier("redisTemplate")
    private RedisTemplate redisTemplate;

    @Resource
    private StringRedisTemplate stringRedisTemplate;


    /**
     * 登录
     * @param userName
     * @param pwd
     * @return
     */
    @PostMapping("/movieUserLogin")
    @ApiOperation("电影用户登录")
    public ResponseResult<Map> movieUserLogin(@RequestParam(value = "userName",required = true) String userName,@RequestParam(value = "pwd",required = true) String pwd){
        log.info("login info:{}>>>{}",userName,pwd);
        MovieUserInfo movie = movieUsersServices.movieUserLogin(userName);
        //加密
        String md5Pwd = DigestUtils.md5DigestAsHex(pwd.getBytes());
        log.info("password:{}",md5Pwd);
        if (ObjectUtils.isEmpty(movie)) return new ResponseResult<>(ResponseCodeEnum.USERNAME_NOT_NULL.getCode(),ResponseCodeEnum.USERNAME_NOT_NULL.getMsg());
        if (StringUtils.equals(movie.getUserPassword(),md5Pwd)){
            Map map = new HashMap<>();
            String token = JwtUtil.createJWT(UUID.randomUUID().toString(),movie.toString(),60*60*24);
            //此处stringRedisTemplate 的set参数key,value都为String。如果value需要存对象，可以将对象转换成json字符串存入。
            //将真正的秘钥(解密后的)存入redis中
            stringRedisTemplate.opsForValue().set("movie-jwt", JwtUtil.parseJWT(token).getSubject());
            stringRedisTemplate.opsForValue().set("movieuser", JSON.toJSONString(movie));
//            redisTemplate.opsForValue().set(Constance.TOKEN_KEY+token,movie);
            log.info(">>> 用户登录信息 >>> token:{} --- user:{}",token,movie.toString());
            //取出
//            String userStr = stringRedisTemplate.opsForValue().get(Constance.TOKEN_KEY+token);
//            MovieUserInfo userInfo = JSON.parseObject(userStr, MovieUserInfo.class);
//            MovieUserInfo users =(MovieUserInfo) redisTemplate.opsForValue().get(Constance.TOKEN_KEY+token);
//            log.info("redis-user:{}",users);
            map.put("token",token);
            map.put("currentUser",movie);
            return new ResponseResult<Map>(ResponseCodeEnum.SUCCESS.getCode(),ResponseCodeEnum.SUCCESS.getMsg(),map);
        }else {
            return new ResponseResult<Map>(ResponseCodeEnum.PASSWORD_ERROR.getCode(),ResponseCodeEnum.PASSWORD_ERROR.getMsg());
        }
    }

    /**
     * 注册
     * @param movieUserInfo
     * @return
     * userId有判断注解,所以默认-1L
     */
    @PostMapping("/movieUserRegister")
    @ApiOperation("电影用户注册")
    public ResponseResult<Integer> movieUserRegister(@Valid @RequestBody MovieUserInfo movieUserInfo){
        log.info("注册信息:{}",movieUserInfo.toString());
        Integer result = movieUsersServices.movieUserRegister(movieUserInfo);
        if (result < 0){
            return new ResponseResult<>(ResponseCodeEnum.USER_REGISTER_ERROR.getCode(),ResponseCodeEnum.USER_REGISTER_ERROR.getMsg(),result);
        }
        return new ResponseResult<>(ResponseCodeEnum.SUCCESS.getCode(),ResponseCodeEnum.SUCCESS.getMsg());
    }

    /**
     * 修改密码
     * @param updatePwdVo
     * @return
     */
    @PostMapping("/updateUserPwd")
    @RequiredToken
    public ResponseResult<Boolean> updateUserPwd(@Valid @RequestBody UpdatePwdVo updatePwdVo){
        Boolean result = movieUsersServices.getMovieUserByUserId(updatePwdVo);
        if (!result){
            return new ResponseResult<>(ResponseCodeEnum.FAIL.getCode(),ResponseCodeEnum.FAIL.getMsg(),false);
        }
        return new ResponseResult<>(ResponseCodeEnum.SUCCESS.getCode(),ResponseCodeEnum.SUCCESS.getMsg(),true);
    }

    /**
     * 修改用户信息
     * @param userName 用户名
     * @param userDescript 描述
     * @return ResponseResult
     * 两个不能都为空,前端判断
     */
    @PostMapping("/updateUserInfo/{id}")
    @RequiredToken
    public ResponseResult updateUserInfoById(@PathVariable("id") Long userId,@RequestParam("userName") String userName,@RequestParam("userDescript") String userDescript){
        Boolean result = movieUsersServices.updateUserInfoById(userId,userName,userDescript);
        if (result){
            return new ResponseResult(ResponseCodeEnum.SUCCESS.getCode(),ResponseCodeEnum.SUCCESS.getMsg());
        }
        return new ResponseResult(ResponseCodeEnum.FAIL.getCode(),ResponseCodeEnum.FAIL.getMsg());
    }

    /**
     * 登出
     * @param token
     * @param session
     * @return
     */
    @ApiOperation("注销登陆")
    @DeleteMapping("/userloginout")
    @RequiredToken
    public ResponseEntity loginout(HttpServletRequest request, HttpSession session) {
        //根据token删除redis中用户信息
        redisTemplate.delete(TOKEN_KEY+request.getAttribute("token"));
        session.removeAttribute("token");
        session.removeAttribute("curruser");
        return new ResponseEntity(HttpStatus.NO_CONTENT);
    }

}
